package com.grapecity;

import com.dingtalk.api.DefaultDingTalkClient;
import com.taobao.api.TaobaoRequest;
import com.taobao.api.TaobaoResponse;

/**
 * @author ben
 * Because DingTalk's API lacks the capability to fully retrieve certain data.
 * Therefore, it requires repeatedly calling the API, which can easily trigger the QPS (Queries Per Second) limit.
 * When the QPS limit is reached, enforce a mandatory 1-second wait.
 */
public class ApiUtil {
    
    static final String QPS_ERROR_CODE_APP = "90018";
    static final String QPS_ERROR_CODE_APP_NEW_VERSION = "Forbidden.AccessDenied.QpsLimitForAppkeyAndApi";
    static final String QPS_ERROR_CODE_API = "90002";
    static final String QPS_ERROR_CODE_API_NEW_VERSION = "Forbidden.AccessDenied.QpsLimitForApi";
    static final int QPS_LIMIT_TIME = 1000;


    public static  <T extends TaobaoResponse> T sendTaoBaoRequest(String url, TaobaoRequest<T> request) {
        return sendTaoBaoRequest(url, request,null,0);
    }

    public static  <T extends TaobaoResponse> T sendTaoBaoRequest(String url, TaobaoRequest<T> request,String appId,String appSecret) {
        return sendTaoBaoRequest(url, request,appId,appSecret,0);
    }

    public static  <T extends TaobaoResponse> T sendTaoBaoRequest(String url, TaobaoRequest<T> request, String accessToken) {
        return sendTaoBaoRequest(url, request, accessToken,0);
    }

    private static <T extends TaobaoResponse> T sendTaoBaoRequest(String url, TaobaoRequest<T> request, String accessToken, int retryCount) {
        DefaultDingTalkClient client = new DefaultDingTalkClient(url);
        T response;
        try {
            response = client.execute(request, accessToken);
            if (!response.getErrorCode().equals("0"))
            {
                String subCode = response.getSubCode();
                if (isQPSErrorCode(subCode) && retryCount < 1)
                {
                    // for qps
                    Thread.sleep(QPS_LIMIT_TIME);
                    response = sendTaoBaoRequest(url, request,accessToken,retryCount + 1);
                }
                else
                {
                    throw new Exception(response.toString());
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    private static <T extends TaobaoResponse> T sendTaoBaoRequest(String url, TaobaoRequest<T> request, String appId,String appSecret, int retryCount) {
        DefaultDingTalkClient client = new DefaultDingTalkClient(url);
        T response;
        try {
            response = client.execute(request, appId,appSecret);
            if (!response.getErrorCode().equals("0"))
            {
                String subCode = response.getSubCode();
                if (isQPSErrorCode(subCode) && retryCount < 1)
                {
                    // for qps
                    Thread.sleep(QPS_LIMIT_TIME);
                    response = sendTaoBaoRequest(url, request,appId,appSecret,retryCount + 1);
                }
                else
                {
                    throw new Exception(response.toString());
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    public static boolean isQPSErrorCode(String code)
    {
        return QPS_ERROR_CODE_API.equals(code)  || QPS_ERROR_CODE_API_NEW_VERSION.equals(code)
                ||  QPS_ERROR_CODE_APP.equals(code) ||  QPS_ERROR_CODE_APP_NEW_VERSION.equals(code);
    }

}
